package com.torry.workflow.service.user.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.torry.workflow.api.user.api.UserApi;
import com.torry.workflow.api.user.dto.UserPageDTO;
import com.torry.workflow.api.user.entity.*;
import com.torry.workflow.common.base.result.LoginResult;
import com.torry.workflow.common.exception.BizException;
import com.torry.workflow.common.util.JwtUtil;
import com.torry.workflow.service.user.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService
@Component
public class UserFacade implements UserApi {
    @Resource
    private IUserService iUserService;
    @Resource
    private IUserRoleService iUserRoleService;

    @Resource
    private IRoleMenuService iRoleMenuService;
    @Resource
    private IMenuService iMenuService;
    @Resource
    private IRoleService iRoleService;

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public LoginResult login(String username, String password) {
        User user = iUserService.getOne(new QueryWrapper<User>().eq("deleted", 0).eq("username", username));
        if (user == null) throw new BizException(400, "用户名不存在");
        if (!password.equals(user.getPassword())) {
            throw new BizException(400, "密码错误");
        }
        if (user.getStatus() != 0) {
            throw new BizException(400, "账号不可用");
        }
        String token = JwtUtil.sign(username, user.getId());
        return LoginResult.builder().token(token).build();
    }

    /**
     * 保存用户信息
     *
     * @return
     */
    @Override
    @Transactional
    public void saveUser(User user) {
        if (userIsExist(user)) {
            throw new BizException(400, "用户名已存在");
        }

        Integer userId = user.getId();
        iUserRoleService.update(new UpdateWrapper<UserRole>().set("deleted", 1).eq("user_id", userId));
        List<UserRole> userRoles = new ArrayList<>();
        List<Integer> roleIds = user.getRoleIds();
        roleIds.forEach(roleId -> {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(user.getId());
            userRoles.add(userRole);
        });
        iUserService.saveOrUpdate(user);
        if (CollectionUtils.isNotEmpty(userRoles)) {
            iUserRoleService.saveBatch(userRoles);
        }
    }


    private boolean userIsExist(User user) {
        User userInfo = iUserService.getOne(new QueryWrapper<User>().eq("deleted", 0).eq("username", user.getUsername()));
        if (user.getId() == null) {
            return userInfo != null;
        }
        return userInfo != null && !userInfo.getId().equals(user.getId());
    }

    /**
     * 用户分页列表
     *
     * @param dto
     * @return
     */
    @Override
    public IPage userList(UserPageDTO dto) {
        IPage<User> page = iUserService.page(dto.page(), new QueryWrapper<User>()
                .eq("deleted", 0)
                .like(StringUtils.isNotBlank(dto.getEmail()), "email", dto.getEmail())
                .like(StringUtils.isNotBlank(dto.getUsername()), "username", dto.getUsername())
                .like(StringUtils.isNotBlank(dto.getName()), "name", dto.getName())
                .eq(dto.getId() != null, "id", dto.getId()));
        page.getRecords().forEach(user -> {
            List<Integer> roleIds = iUserRoleService.listObjs(new QueryWrapper<UserRole>()
                    .select("role_id")
                    .eq("deleted", 0)
                    .eq("user_id", user.getId()), roleId -> Integer.parseInt(roleId.toString()));
            if (CollectionUtils.isNotEmpty(roleIds)) {
                List<String> roleNames = iRoleService.listObjs(new QueryWrapper<Role>().select("name").eq("deleted", 0).in("id", roleIds),
                        roleName -> roleName.toString());
                user.setRoleIds(roleIds);
                user.setRoleNames(roleNames);
            }

        });
        return page;
    }


    /**
     * 登陆后， 获取用户信息， 包含菜单
     *
     * @param id
     * @return
     */
    @Override
    public User getUserInfo(Integer id) {
        User user = iUserService.getById(id);
        List<Integer> roleIds = iRoleService.getRoleIdsByUserId(id);
        if (CollectionUtils.isNotEmpty(roleIds)) {
            List<Integer> menuIdList = new ArrayList<>();
            roleIds.forEach(roleId -> {
                List<Integer> menuIds = iRoleMenuService.listObjs(new QueryWrapper<RoleMenu>().select("menu_id")
                                .eq("deleted", 0)
                                .eq("role_id", roleId),
                        (menuId) -> Integer.parseInt(menuId.toString()));
                menuIdList.addAll(menuIds);
            });
            if (CollectionUtils.isNotEmpty(menuIdList)) {
                List<Menu> menus = iMenuService.list(new QueryWrapper<Menu>().eq("deleted", 0).in("id", menuIdList));
                if (CollectionUtils.isNotEmpty(menus)) {
                    user.setMenus(menus);
                    user.setMenuIds(menuIdList.stream().distinct().collect(Collectors.toList()));
                }
            }

        }

        return user;
    }

    @Override
    @Transactional
    public void updateStatus(Integer userId, Integer status) {
        iUserService.update(new UpdateWrapper<User>().set("status", status).eq("id", userId));
    }

    @Override
    @Transactional
    public void deleteUserById(Integer id) {
        iUserService.update(new UpdateWrapper<User>().set("deleted", 1).eq("id", id));
    }

    @Override
    public List<User> getUsersByIds(List<Integer> userIds) {
        return iUserService.list(new QueryWrapper<User>().eq("deleted", 0).in("id", userIds));
    }

    @Override
    public List<User> allUsers() {
        return iUserService.list(new QueryWrapper<User>().eq("deleted", 0));
    }
}
